// 引入工具类
import { isValidPhone, isFunction } from './utils';

// 引入配置
import { IMAGE_SECURITY_APPID } from '../config';
import { TAB_BAR_PAGE } from '../constants/route';

// 提示、遮罩

/**
 * 加载loading
 * @param {String} title 加载提示内容
 * @param {Number} time 提示时间，默认：0，不自动关闭
 */
const showLoading = (title, time = 0) => {
    wx.showLoading({
        title,
        mask: true,
    })
    if (time) {
        setTimeout(() => {
            wx.hideLoading();
        }, time);
    }
};

/**
 * 关闭加载
 */
const hideLoading = () => {
    wx.hideLoading();
};

/**
 * toast 提示信息
 * @param {String} title 提示内容
 */
const tipToast = (title, duration = 2000) => {
    wx.showToast({
        title,
        icon: 'none',
        duration
    })
};

/**
 * toast success 提示信息
 * @param {String} title 提示内容
 */
const tipSuccess = (title, duration = 2000) => {
    wx.showToast({
        title,
        icon: 'success',
        duration
    })
};

/**
 * toast error 提示信息
 * @param {String} title 提示内容
 */
const tipError = (title, duration = 2000) => {
    wx.showToast({
        title,
        icon: 'error',
        duration
    })
};

const showModal = ({ title = '提示', content = ''}) => {
    return new Promise((resolve, reject) => {
        wx.showModal({
            title,
            content,
            success(res) {
                resolve(res);
            },
            fail(err) {
                reject(err);
            },
        });
    });
}

// 界面相关

/**
 * 设置页面标题
 * @param {String} title 标题名称
 */
const setTitle = (title) => {
    wx.setNavigationBarTitle({
        title,
    });
};

/**
 * 设置手机状态栏字体颜色
 * @param {String} color 颜色
 */
const setPhoneBarColor = (color) => {
    wx.setNavigationBarColor({
        backgroundColor: color,
        // animation: {
        //   duration: 400,
        //   timingFunc: 'easeIn'
        // }
    });
};

/**
 * 设置app背景色
 * @param {String} color 颜色
 */
const setAppBackground = (mode) => {
    wx.setBackgroundColor({
        backgroundColor: color,
        backgroundColorTop: color,
        backgroundColorBottom: color,
    });
};

/**
 * 隐藏主页
 */
const hideHomeButton = () => {
    wx.hideHomeButton({
        complete: (res) => {
            console.info('隐藏主页');
        },
    })
};

/**
 * 隐藏下拉刷新操作
 */
const hidePullDownLoading = () => {
    wx.stopPullDownRefresh();
};

/**
 * 隐藏tabbar
 */
const hideTabbar = () => {
    wx.hideTabBar({
        animation: true,
        fail: function () {
            hideTabbar();
        },
    });
};

/**
 * 显示tabbar
 */
const showTabbar = () => {
    wx.showTabBar({
        animation: false,
        fail: function () {
            showTabbar();
        },
    });
};

/**
 * 获取菜单按钮（右上角胶囊按钮）的布局位置信息
 */
const getMenuButtonBoundingClientRect = () => {
    return wx.getMenuButtonBoundingClientRect ? wx.getMenuButtonBoundingClientRect() : null;
};

// 路由相关

/**
 * 处理页面跳转参数为字符串
 * @param {Object} param 页面参数
 */
const _dealParam = (param) => {
    let query = '';
    for (let key in param) {
        query += `${key}=${param[key]}&`;
    }
    return `${query ? '?' + query : ''}`;
};

/**
 * 路由跳转
 * @param {String} path 跳转路径
 * @param {Object} param 跳转参数
 */
const navTo = (path, param = {}) => {
    wx.navigateTo({
        url: `${path}${_dealParam(param)}`,
        fail: function (err) {
            console.error(`navTo 错误: ${JSON.stringify(err)}`);
        },
    })
};

/**
 * 路由跳转
 * @param {String} path 跳转路径
 * @param {Object} param 跳转参数
 */
const navToAction = (path, param = {}, action) => {
    wx.navigateTo({
        url: `${path}${_dealParam(param)}`,
        fail: function (err) {
            console.error(`navTo 错误: ${JSON.stringify(err)}`);
        },
        ...action,
    })
};

/**
 * 返回页面
 * @param {Number} pageNum 返回的页面数
 */
const navBack = (pageNum = 1) => {
    wx.navigateBack({
        delta: pageNum,
        fail: function (err) {
            console.error(`navTo 错误: ${JSON.stringify(err)}`);
            switchTab(TAB_BAR_PAGE.index);
        },
    });
};

/**
 * 页面跳转
 * @param {String} path 页面地址
 * @param {Object}} param 页面参数
 */
const redirectTo = (path, param = {}) => {
    wx.redirectTo({
        url: `${path}${_dealParam(param)}`,
        fail: function (err) {
            console.error(`redirectTo 错误: ${JSON.stringify(err)}`);
        },
    })
};

/**
 * 页面重载，关闭其他页面
 * @param {String} path 页面地址
 * @param {Object} param 页面参数
 */
const reLaunchTo = (path, param = {}) => {
    wx.reLaunch({
        url: `${path}${_dealParam(param)}`,
        fail: function (err) {
            console.error(`reLaunchTo 错误: ${JSON.stringify(err)}`);
        },
    })
};

/**
 * 跳转到 tabBar 页面
 * @param {String} path 页面地址
 */
const switchTab = (path) => {
    wx.switchTab({
        url: path,
        fail: function (err) {
            console.error(`switchTab 错误: ${JSON.stringify(err)}`);
        },
    })
};

/**
 * 跳转至其他小程序
 * @param {String} appId 
 * @param {String} path 页面地址
 * @param {Object} param 页面参数
 */
const navToMiniProgram = (appId, path = 'page/index/index', param = {}) => {
    wx.navigateToMiniProgram({
        appId,
        path,
        extraData: param,
        fail: function (err) {
            console.error(`navigateToMiniProgram 错误: ${JSON.stringify(err)}`);
        },
    })
};

// 本地数据保存方法

/**
 * 添加一个值到本地 storage
 * @param {String} name 名称
 * @param {Object} value 值
 * @param {Number} days 有效期，单位：天
 */
const setItem = (name, value, days = 1) => {
    const expires = new Date(Date.now() + days * 86400000);
    try {
        delItem(name);
        wx.setStorageSync(name, {
            value,
            expires,
        });
    } catch (error) {
        console.error(`setItem 出错: ${error}`);
    }
};

/**
 * 获取一个本地 storage 的值
 * @param {String} name 名称
 */
const getItem = (name) => {
    try {
        var obj = wx.getStorageSync(name)
        if (obj) {
            const now = new Date().getTime();
            const expires = new Date(obj.expires).getTime();
            if (now <= expires) {
                return obj.value;
            } else {
                console.warn(`getItem 警告: ${name} 过期！`);
            }
        }
        return '';
    } catch (error) {
        console.error(`getItem 出错: ${error}`);
    }
};

/**
 * 从本地 storage 删除一条数据记录
 * @param {String} name 名称
 */
const delItem = (name) => {
    try {
        wx.removeStorageSync(name);
    } catch (error) {
        console.error(`delItem 出错: ${error}`);
    }
};

/**
 * 清除所有的本地 storage 数据
 */
const clearItems = () => {
    try {
        wx.clearStorageSync();
    } catch (error) {
        console.error(`clearItems 出错: ${error}`);
    }
};

/**
 * 设置没有时效性的本地数据
 * @param {String} name 名称
 * @param {Object} value 值
 */
const setForEverData = (name, value) => {
    try {
        wx.setStorageSync(name, value);
    } catch (error) {
        console.error(`setForEverData 出错: ${error}`);
        setForEverData(name, value);
    }
};

/**
 * 获取没有时效性的本地数据
 * @param {String} name 名称
 */
const getForEverData = (name) => {
    try {
        return wx.getStorageSync(name);
    } catch (error) {
        console.error(`getForEverData 出错: ${error}`);
        return '';
    }
};

// 图片、视频、文件

/**
 * 进行图片安全性检查
 * @param {String} filePath 文件地址
 */
const checkImageSecurity = (filePath) => {
    // showLoading('图片检查中...');
    return new Promise((reslove, reject) => {
        reslove(true);
        return;
        wx.serviceMarket.invokeService({
            service: IMAGE_SECURITY_APPID,
            api: 'imgSecCheck',
            data: {
                "Action": "ImageModeration",
                "Scenes": ["PORN", "POLITICS", "TERRORISM"],
                "ImageUrl": new wx.serviceMarket.CDN({
                    type: 'filePath',
                    filePath,
                }),
                "ImageBase64": "",
                "Config": "",
                "Extra": ""
            },
        }).then(res => {
            const { Suggestion } = res.data.Response;
            const result = Suggestion && Suggestion == 'PASS';
            reslove(result);
            hideLoading();
        }).catch(err => {
            reslove(false);
            hideLoading();
        });
    })
};

/**
 * 选择图片
 * @param {Object} params 
 */
const chooseImage = (params = {}) => {
    const { count = 1, sizeType = ['original', 'compressed'] } = params;
    return new Promise((resolve, reject) => {
        wx.chooseImage({
            count,
            sizeType,
            success(res) {
                const tempFilePaths = res.tempFilePaths;
                console.log('res.tempFilePaths=>', res.tempFilePaths)
                console.log('res.tempFiles=>', res.tempFiles)
                resolve(tempFilePaths);
            },
            fail(err) {
                reject(err);
            },
        });
    });
};

/**
 * 获取图片信息
 * @param {String} filePath 
 */
const getImageInfo = (filePath) => {
    return new Promise((resolve, reject) => {
        wx.getImageInfo({
            src: filePath,
            success(res) {
                resolve(res);
            },
            fail(err) {
                reject(err);
            },
        });
    });
};

/**
 * 保存图片到系统相册
 * @param {String} filePath 
 */
const saveImage = (filePath) => {
    return new Promise((resolve, reject) => {
        wx.saveImageToPhotosAlbum({
            filePath,
            success(res) {
                resolve(res);
            },
            fail(err) {
                reject(err);
            },
        })
    });
};

/**
 * 压缩图片
 * @param {String} filePath 
 * @param {Number} quality 
 */
const compressImage = (filePath, quality = 80) => {
    return new Promise((resolve, reject) => {
        wx.compressImage({
            src: filePath,
            quality,
            success(res) {
                const tempFilePath = res.tempFilePath;
                resolve(tempFilePath);
            },
            fail(err) {
                reject(err);
            },
        })
    });
};

/**
 * 预览图片
 * @param {String} current 
 * @param {Array} urls 
 */
const previewImage = (current, urls) => {
    wx.previewImage({
        current,
        urls,
    });
};

/**
 * 选择视频
 * @param {Number} duration 
 */
const chooseVideo = (duration) => {
    return new Promise((resolve, reject) => {
        wx.chooseVideo({
            maxDuration: duration || 60,
            success(res) {
                const tempFilePath = res.tempFilePath;
                resolve(tempFilePath);
            },
            fail(err) {
                reject(err);
            },
        });
    });
};

/**
 * 获取视频信息
 * @param {String} filePath 
 */
const getVideoInfo = (filePath) => {
    return new Promise((resolve, reject) => {
        wx.getVideoInfo({
            src: filePath,
            success(res) {
                resolve(res);
            },
            fail(err) {
                reject(err);
            },
        });
    });
};

/**
 * 选择图片、视频
 * @param {Object} param 
 * @returns 
 */
const chooseMedia = ({ count = 1, duration = 60 }) => {
    return new Promise((resolve, reject) => {
        wx.chooseMedia({
            count,
            maxDuration: duration,
            success(res) {
                const tempFilePath = res.tempFiles.tempFilePath;
                resolve(tempFilePath);
            },
            fail(err) {
                reject(err);
            },
        })
    });
};

/**
 * 预览图片和视频
 * @param {String} current 
 * @param {Array} urls 
 */
const previewMedia = (current, urls) => {
    wx.previewMedia({
        current,
        urls,
    });
};

/**
 * 上传文件
 * @param {Object} params 
 */
const uploadFile = (params) => {
    return new Promise((resolve, reject) => {
        wx.uploadFile({
            ...params,
            success(res) {
                resolve(res);
            },
            fail(err) {
                console.error(`uploadFile 错误: ${JSON.stringify(err)}`);
                reject(err);
            },
        })
    });
};

/**
 * 下载文件
 * @param {String} url 
 */
const downloadFile = (url) => {
    return new Promise((resolve, reject) => {
        wx.downloadFile({
            url,
            success(res) {
                resolve(res);
            },
            fail(err) {
                console.error(`downloadFile 错误: ${JSON.stringify(err)}`);
                reject(err);
            },
        })
    });
};

/**
 * 读取文件
 * @param {String} filePath 
 * @param {String} encoding 
 */
const readFile = (filePath, encoding = 'base64') => {
    return new Promise((resolve, reject) => {
        wx.getFileSystemManager().readFile({
            filePath,
            encoding,
            success(res) {
                resolve(res);
            },
            fail(err) {
                console.error(`readFile 错误: ${JSON.stringify(err)}`);
                reject(err);
            },
        }) 
    });
};

// 平台相关类方法封装

/**
 * 获取登录code
 */
const getCode = () => {
    return new Promise((resolve, reject) => {
        wx.login({
            success: res => {
                resolve(res.code);
            },
            fail: err => {
                reject(false);
            }
        });
    });
};

/**
 * 获取设置setting
 */
const getSetting = () => {
    return new Promise((resolve, reject) => {
        wx.getSetting({
            success: res => {
                resolve(res.authSetting);
            },
            fail: err => {
                reject(false);
            }
        });
    });
};

/**
 * 获取用户信息
 * @param {String} desc 
 */
const getUserInfo = (desc = '用于完善用户资料') => {
    return new Promise((resolve, reject) => {
        if (canIUse('getUserProfile')) {
            wx.getUserProfile({
                desc,
                success: res => {
                    resolve(res.userInfo);
                },
                fail: err => {
                    reject(err);
                }
            })
        } else {
            wx.getUserInfo({
                success: res => {
                    resolve(res.userInfo);
                },
                fail: err => {
                    reject(err);
                }
            })
        }
    });
};

/**
 * 获取用户信息授权状态
 * @param {Object} authInfo 
 */
const isAuthUserInfo = (authInfo) => {
    return authInfo['scope.userInfo'];
};

/**
 * 是否授权获取位置信息
 * @param {Object} authInfo 
 */
const isAuthGetLocation = (authInfo) => {
    return authInfo['scope.userLocation'];
};

/**
 * 获取系统信息
 */
const getSysInfo = () => {
    try {
        return wx.getSystemInfoSync();
    } catch (error) {
        return {};
    }
};

/**
 * 打开扫码
 */
const openScan = () => {
    return new Promise((reslove, reject) => {
        wx.scanCode({
            success(res) {
                reslove(res.result);
            },
            fail(err) {
                reject(err);
            },
        })
    });
};

/**
 * 拨打电话
 * @param {number} phoneNumber 电话号码
 */
const callPhone = (phoneNumber) => {
    if (!isValidPhone(phoneNumber)) {
        wx.showToast({
            icon: 'none',
            title: '号码错误',
        })
        return;
    }
    wx.makePhoneCall({
        phoneNumber,
    })
};

/**
 * 地理位置信息
 */
const getLocationInfo = () => {
    return new Promise((resolve, reject) => {
        wx.getLocation({
            type: 'wgs84',
            success(res) {
                const latitude = res.latitude
                const longitude = res.longitude
                resolve({
                    latitude,
                    longitude,
                });
            }
        })
    });
};

/**
 * 打开地图选择位置
 */
const chooseLocation = (params = {}) => {
    return new Promise((resolve, reject) => {
        wx.chooseLocation({
            ...params,
            success(res) {
                resolve(res);
            },
        });
    });
};

/**
 * 打开地图选择位置
 */
const chooseAddress = () => {
    return new Promise((resolve, reject) => {
        wx.chooseAddress({
            success: function (res) {
                resolve({
                    username: res.userName,
                    mobile: res.telNumber,
                    address: `${res.cityName}${res.countyName}${res.detailInfo}`,
                    code: res.postalCode,
                });
            },
            fail: function (err) {
                reject(false);
            },
        })
    });
};

/**
 * 订阅消息
 * @param {Array} tmplIds 
 */
const subscribeMessage = (tmplIds) => {
    return new Promise((resolve, reject) => {
        wx.requestSubscribeMessage({
            tmplIds,
            success(res) {
                let isAll = true;
                for (let key in res) {
                    if (key !== 'errMsg' && res[key] !== 'accept') {
                        isAll = false;
                    }
                }
                resolve({ isAll, ...res });
            },
            fail(err) {
                resolve(false);
            },
        });
    });
};

/**
 * 复制文本
 * @param {String} text 
 * @param {Function} callback 
 */
const copyText = (text, callback) => {
    wx.setClipboardData({
        data: text,
        success (res) {
            callback && isFunction(callback) ? callback() : tipSuccess('复制成功');
        }
      })
};

/**
 * 能否使用
 * @param {String} name 
 */
const canIUse = (name) => {
    return wx.canIUse(name);
};

/**
 * 更新
 */
const getUpdateManager = () => {
    return wx.getUpdateManager();
};

module.exports = {
    // 提示
    showLoading,
    hideLoading,
    tipToast,
    tipSuccess,
    tipError,
    showModal,
    // 本地数据存储
    setItem,
    getItem,
    delItem,
    clearItems,
    setForEverData,
    getForEverData,
    // 界面操作
    setTitle,
    setPhoneBarColor,
    setAppBackground,
    hideHomeButton,
    hidePullDownLoading,
    hideTabbar,
    showTabbar,
    getMenuButtonBoundingClientRect,
    // 路由
    navTo,
    navToAction,
    navBack,
    redirectTo,
    reLaunchTo,
    switchTab,
    navToMiniProgram,
    // 图片、视频、文件
    checkImageSecurity,
    chooseImage,
    getImageInfo,
    saveImage,
    compressImage,
    previewImage,
    chooseVideo,
    getVideoInfo,
    chooseMedia,
    previewMedia,
    uploadFile,
    downloadFile,
    readFile,
    // 平台功能
    getCode,
    getSetting,
    getUserInfo,
    isAuthUserInfo,
    isAuthGetLocation,
    getSysInfo,
    openScan,
    callPhone,
    getLocationInfo,
    chooseLocation,
    chooseAddress,
    subscribeMessage,
    copyText,
    canIUse,
    getUpdateManager,
};